package com.earnings.okhttputils.utils.weixin;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.util.Xml;

import com.earnings.okhttputils.utils.bean.WeixinPayData;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import org.xmlpull.v1.XmlPullParser;

import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * Created by yy on 2015/7/25.
 */
public class WeiXinTool {
    private static final String TAG = "MicroMsg.SDKSample.PayActivity";
    private Context context;
    private PayReq req;
    final IWXAPI msgApi;

    StringBuffer sb;


    public WeiXinTool(Context context) {
        this.context = context;
        req = new PayReq();
        sb = new StringBuffer();
        msgApi = WXAPIFactory.createWXAPI(context, null);
        msgApi.registerApp(Constants.APP_ID);
    }

    public void pay() {
        GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
        getPrepayId.execute();
    }


    /**
     * 生成签名
     */

    private String genPackageSign(List<BasicNameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(Constants.API_KEY);


        String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", packageSign);
        return packageSign;
    }

    private String genAppSign(List<BasicNameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(Constants.API_KEY);

        this.sb.append("sign str\n" + sb.toString() + "\n\n");
        String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", appSign);
        return appSign;
    }

    private String toXml(List<BasicNameValuePair> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<" + params.get(i).getName() + ">");


            sb.append(params.get(i).getValue());
            sb.append("</" + params.get(i).getName() + ">");
        }
        sb.append("</xml>");

        Log.e("orion", "拼接xml" + sb.toString());
        try {
            return new String(sb.toString().getBytes(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }
    class BasicNameValuePair {
        private String Name;
        private String Value;

        public BasicNameValuePair(String Key, String Value) {
            this.Name = Key;
            this.Value = Value;
        }

        public String getName() {
            return Name;
        }

        public void setName(String name) {
            Name = name;
        }

        public String getValue() {
            return Value;
        }

        public void setValue(String value) {
            Value = value;
        }
    }
    private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String, String>> {

        private ProgressDialog dialog;


        @Override
        protected void onPreExecute() {
            dialog = ProgressDialog.show(context, "", "");
        }

        @Override
        protected void onPostExecute(Map<String, String> result) {
            if (dialog != null) {
                dialog.dismiss();
            }
            /** doInBackground 方法后获取result */
            sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");

            genPayReq(result);

        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
        }

        @Override
        protected Map<String, String> doInBackground(Void... params) {
            String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");//unifiedorder
            String entity = genProductArgs();

            Log.e("orion", "执行之前" + entity);

            byte[] buf = Util.httpPost(url, entity);

            String content = new String(buf);
            Log.e("orion", "执行之后" + content);
            Map<String, String> xml = decodeXml(content);
            return xml;
        }
    }


    public Map<String, String> decodeXml(String content) {

        try {
            Map<String, String> xml = new HashMap<String, String>();
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(new StringReader(content));
            int event = parser.getEventType();
            while (event != XmlPullParser.END_DOCUMENT) {

                String nodeName = parser.getName();
                switch (event) {
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:
                        if ("xml".equals(nodeName) == false) {
                            //实例化student对象
                            xml.put(nodeName, parser.nextText());
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                }
                event = parser.next();
            }

            return xml;
        } catch (Exception e) {
            Log.e("orion", e.toString());
        }
        return null;

    }


    private String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest( String.valueOf(random.nextInt(10000)).getBytes());
    }

    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }


    private String genOutTradNo() {
        Random random = new Random();
        return MD5.getMessageDigest( String.valueOf(random.nextInt(10000)).getBytes());
    }

    public void setData(Map<String, String> mapList) {
        this.mapList = mapList;
    }

    public void setData(String appid, String body, String mch_id, String nonce_str, String out_trade_no, String spbill_create_ip, String
            total_fee, String trade_type, String sign, String notify_url) {
        mapList = new HashMap<>();
        mapList.put("appid", appid);
        mapList.put("body", body);
        mapList.put("mch_id", mch_id);
        mapList.put("nonce_str", nonce_str);
        mapList.put("out_trade_no", out_trade_no);
        mapList.put("spbill_create_ip", spbill_create_ip);
        mapList.put("total_fee", total_fee);
        mapList.put("trade_type", trade_type);
        mapList.put("sign", sign);
        mapList.put("notify_url", notify_url);
    }

    private Map<String, String> mapList;

    //
    private String genProductArgs() {

        try {
            List<BasicNameValuePair> packageParams = new LinkedList<BasicNameValuePair>();

//            packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
//            packageParams.add(new BasicNameValuePair("body", "weixin"));
//            packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
//            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
//            packageParams.add(new BasicNameValuePair("notify_url", "http://121.40.35.3/test"));
//            packageParams.add(new BasicNameValuePair("out_trade_no",genOutTradNo()));
//            packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));
//            packageParams.add(new BasicNameValuePair("total_fee", "1"));
//            packageParams.add(new BasicNameValuePair("trade_type", "APP"));

            packageParams.add(new BasicNameValuePair("appid", mapList.get("appid")));
            packageParams.add(new BasicNameValuePair("body", mapList.get("body")));
            packageParams.add(new BasicNameValuePair("mch_id", mapList.get("mch_id")));
            packageParams.add(new BasicNameValuePair("nonce_str", mapList.get("nonce_str")));
            packageParams.add(new BasicNameValuePair("notify_url", mapList.get("notify_url")));
            packageParams.add(new BasicNameValuePair("out_trade_no", mapList.get("out_trade_no")));
            packageParams.add(new BasicNameValuePair("spbill_create_ip", mapList.get("spbill_create_ip")));
            packageParams.add(new BasicNameValuePair("total_fee", mapList.get("total_fee")));
            packageParams.add(new BasicNameValuePair("trade_type", mapList.get("trade_type")));

            String sign = genPackageSign(packageParams);
            packageParams.add(new BasicNameValuePair("sign", sign));

            String xmlstring = toXml(packageParams);


            return xmlstring;

        } catch (Exception e) {
            //Log.e(TAG, "出现异常 " + e.getMessage().toString());
            return null;
        }

    }

    private void genPayReq(Map<String, String> resultunifiedorder) {
        if("FAIL".equals(resultunifiedorder.get("return_code"))){
            return;
        }
        req.appId = Constants.APP_ID;
        req.partnerId = Constants.MCH_ID;
        req.prepayId = resultunifiedorder.get("prepay_id");
        req.packageValue = "Sign=WXPay";
        req.nonceStr = genNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());


        List<BasicNameValuePair> signParams = new LinkedList<BasicNameValuePair>();
        signParams.add(new BasicNameValuePair("appid", req.appId));
        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
        signParams.add(new BasicNameValuePair("package", req.packageValue));
        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

        req.sign = genAppSign(signParams);

        sb.append("sign\n" + req.sign + "\n\n");

        sendPayReq();
        Log.e("orion", "sendPayReq：：：：：：" + signParams.toString());

    }
    public void pay(WeixinPayData weixin) {

        req.appId =weixin.getAppid();
        req.partnerId = weixin.getPartnerid();
        req.prepayId =weixin.getPrepayid();
        req.packageValue = weixin.getPackages();
        req.nonceStr =weixin.getNoncestr();
        req.timeStamp = weixin.getTimestamp();
        req.sign = weixin.getSign();
        sb.append("sign\n" + req.sign + "\n\n");

        sendPayReq();
      //Log.e("orion", "sendPayReq：：：：：：" + signParams.toString());

    }
    private void sendPayReq() {
        msgApi.registerApp(Constants.APP_ID);
        msgApi.sendReq(req);
    }

    public PayReq getReq() {
        return req;
    }

    public void setReq(PayReq req) {
        this.req = req;
    }
}
